namespace ro.EBS.Portal.SkypeStatus
{
    using System;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.ComponentModel;
    using System.Text;
    //using Microsoft.Office.Server;
    //using Microsoft.Office.Server.UserProfiles;
    using Microsoft.SharePoint;
    using System.Reflection;
    using System.Collections.Generic;
    using Microsoft.SharePoint.Utilities;
    using System.IO;

    public class EBSSkypeStatusWebPart : WebPart
    {
        #region # Const

        const string ACCOUNT_NOT_SET = "Error on getting Skype account or account is not set!";
        const string SKYPE_ACCOUNT = "SkypeAccount";
        const string ACCOUNT_QUERY_STRING_KEY = "accountname";
        const string DLL_SIGNATURE = @"Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c";

        #endregion # Const

        #region # Enums

        public enum EIconStyle
        {
            Balloon, BigClassic, SmallClassic, SmallIcon, MediumIcon
        }

        public enum EClickBehavior
        {
            Chat, Call, Add, UserInfo
        }

        #endregion # Enums

        #region # Properties

        [WebBrowsable(true),
         Personalizable(PersonalizationScope.Shared),
         WebDescription("Skype account"),
         Category("Skype Web Part"),
         WebDisplayName("Skype account")]
        public string SkypeAccount
        {
            get;
            set;
        }

        [WebBrowsable(true),
         Personalizable(PersonalizationScope.Shared),
         WebDescription("Profile property name"),
         Category("Skype Web Part"),
         WebDisplayName("Profile property"),
         DefaultValue(SKYPE_ACCOUNT)]
        public string ProfileProperty
        {
            get;
            set;
        }

        [WebBrowsable(true),
         Personalizable(PersonalizationScope.Shared),
         WebDescription("The style of the icon"),
         Category("Skype Web Part"),
         WebDisplayName("Icon style"),
         DefaultValue(EIconStyle.Balloon)]
        public EIconStyle IconStyle
        {
            get;
            set;
        }

        [WebBrowsable(true),
         Personalizable(PersonalizationScope.Shared),
         WebDescription("The behavior of the image when clicked"),
         Category("Skype Web Part"),
         WebDisplayName("Click behavior"),
         DefaultValue(EClickBehavior.Chat)]
        public EClickBehavior ClickBehavior
        {
            get;
            set;
        }

        #endregion # Properties

        #region # Override

        protected override void CreateChildControls()
        {
            LiteralControl litCtrl = new LiteralControl();

            if (SkypeAccount != null && !SkypeAccount.Equals(string.Empty))
            {
                string html = GetHtml(SkypeAccount);
                litCtrl.Text = html;
            }
            else
            {
                string skypeAccount = GetSkypeAccountFromProfile();

                if (!skypeAccount.Equals(string.Empty))
                {
                    string html = GetHtml(skypeAccount);
                    litCtrl.Text = html;
                }
                else
                {
                    litCtrl.Text = ACCOUNT_NOT_SET;
                }
            }

            this.Controls.Add(litCtrl);
        }

        #endregion # Override

        #region # Methods

        private string GetHtml(string skypeAccount)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<script type='text/javascript' src='http://download.skype.com/share/skypebuttons/js/skypeCheck.js'></script>");
            sb.Append("<a href='skype:");
            sb.Append(skypeAccount);
            sb.Append("?");
            sb.Append(ClickBehavior.ToString());
            sb.Append("'><img src='http://mystatus.skype.com/");
            sb.Append(IconStyle);
            sb.Append("/");
            sb.Append(skypeAccount);
            sb.Append("?T=");
            sb.Append(DateTime.Now.Ticks.ToString());
            sb.Append("' style='border: none;' alt='My status' /></a>");

            return sb.ToString();
        }

        private string GetSkypeAccountFromProfile()
        {
            try
            {
                Assembly dllOfficeServer = Assembly.Load(DLL_SIGNATURE);
                Type typeServerContext = dllOfficeServer.GetType("Microsoft.Office.Server.ServerContext");
                MethodInfo getContext = typeServerContext.GetMethod("GetContext", new Type[] { typeof(SPSite) });
                object serverContext = getContext.Invoke(null, new object[] { SPContext.Current.Site });
                Type typeUserProfileManager = dllOfficeServer.GetType("Microsoft.Office.Server.UserProfiles.UserProfileManager");
                ConstructorInfo ci = typeUserProfileManager.GetConstructor(new Type[] { typeServerContext });
                object userProfileManager = ci.Invoke(new object[] { serverContext });

                string loginName = this.Page.Request.QueryString[ACCOUNT_QUERY_STRING_KEY];

                MethodInfo userExists = typeUserProfileManager.GetMethod("UserExists", new Type[] { typeof(string) });
                bool userHasProfile = (bool)userExists.Invoke(userProfileManager, new object[] { loginName });

                if (userHasProfile)
                {
                    MethodInfo userProfileMethod = typeUserProfileManager.GetMethod("GetUserProfile", new Type[] { typeof(string) });
                    object userProfile = userProfileMethod.Invoke(userProfileManager, new object[] { loginName });

                    string propertyName = ProfileProperty == null ||
                                          ProfileProperty.Equals(string.Empty) ?
                                          SKYPE_ACCOUNT : ProfileProperty;

                    Type typeUserProfile = dllOfficeServer.GetType("Microsoft.Office.Server.UserProfiles.UserProfile");
                    PropertyInfo itemProperty = typeUserProfile.GetProperty("Item");
                    string skypeAccount = itemProperty.GetValue(userProfile, new object[] { propertyName }).ToString();

                    return skypeAccount;
                }
                else
                {
                    return string.Empty;
                }

                #region # Old version with reference

                //ServerContext serverContext = ServerContext.GetContext(SPContext.Current.Site);
                //UserProfileManager userProfileManager = new UserProfileManager(serverContext);

                //string loginName = this.Page.Request.QueryString[ACCOUNT_QUERY_STRING_KEY];

                //if (userProfileManager.UserExists(loginName))
                //{
                //    UserProfile userProfile = userProfileManager.GetUserProfile(loginName);
                //    string propertyName = ProfileProperty == null ||
                //                          ProfileProperty.Equals(string.Empty) ?
                //                          SKYPE_ACCOUNT : ProfileProperty;
                //    string skypeAccount = userProfile[propertyName].Value.ToString();

                //    return skypeAccount;
                //}
                //else
                //{
                //    return string.Empty;
                //}

                //return string.Empty;

                #endregion # Old version with reference
            }
            catch (FileNotFoundException exFileNotFound)
            {
                // Could not find the dll in GAC (Microsoft.Office.Server.dll)
                return string.Empty;
            }
            catch (FileLoadException exFileLoad)
            {
                //File was found but could not be loaded
                return string.Empty;
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }

        #endregion # Methods
    }
}
